package cc.rengu.oltp.service.realize.impl;

import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.TxnSensitiveCfgMapper;
import cc.rengu.oltp.service.common.dao.impl.TxnSensitiveCfgMapperImpl;
import cc.rengu.oltp.service.common.entity.TxnSensitiveCfg;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.SensitiveTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizHeader;
import cc.rengu.oltp.service.realize.SensitiveInfoService;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Base64;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 敏感信息脱敏处理服务实现
 * Created by wangcheng on 2021/4/28 10:44
 */
public class SensitiveInfoServiceImpl implements SensitiveInfoService {
    RgLogger rglog = RgLog.getLogger(this.getClass().getName());
    private static final String SENSITIVE_INFO_CACHE_TIME = "300";

    @Override
    public Map<String, String> desensitise(String cacheName, String cacheTime) throws Exception {
        BizHeader bizHeader = new BizHeader();
        ConvertUtil.convertOutput(bizHeader);
        if (StringUtil.isEmptyOrNull(bizHeader.getInstId()) || StringUtil.isEmptyOrNull(bizHeader.getSrcSysId()) ||
                StringUtil.isEmptyOrNull(bizHeader.getTxnNum()) || StringUtil.isEmptyOrNull(bizHeader.getBizType())) {
            rglog.error("无法获取交易信息，不进行敏感信息脱敏处理!");
            return null;
        }
        if (StringUtil.isEmptyOrNull(cacheName) && StringUtil.isEmptyOrNull(bizHeader.getSession())) {
            rglog.error("敏感信息缓存名或者会话ID同时为空，不进行敏感信息脱敏处理!");
            return null;
        }
        /* 敏感信息缓存名为空时，默认以session会话ID为缓存名 */
        cacheName = StringUtil.isEmptyOrNull(cacheName) ? bizHeader.getSession() : cacheName;
        /* 获取交易敏感信息配置信息 */
        TxnSensitiveCfgMapper txnSensitiveCfgMapper = new TxnSensitiveCfgMapperImpl();
        String txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + bizHeader.getBizType().trim() + "00";
        List<TxnSensitiveCfg> txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
        if (null == txnSensitiveCfgList) {
            txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), bizHeader.getBizType(), "00");
            if (null == txnSensitiveCfgList && !"*".equals(bizHeader.getBizType())) {
                rglog.info("查询当前交易通用的敏感信息配置！");
                txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + "*00";
                txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
                if (null == txnSensitiveCfgList) {
                    txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), "*", "00");
                }
            }
        }
        return desensitise(txnSensitiveCfgList, cacheName, cacheTime);
    }

    @Override
    public Map<String, String> desensitise(List<TxnSensitiveCfg> txnSensitiveCfgList, String cacheName, String cacheTime) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Map<String, String> sensitiveMap = new HashMap<>();
        if (null == txnSensitiveCfgList || txnSensitiveCfgList.isEmpty()) {
            rglog.debug("交易敏感配置信息为空，不进行脱敏处理!");
            return null;
        }
        if (StringUtil.isEmptyOrNull(cacheName)) {
            rglog.error("缓存名:{}为空!", cacheName);
            throw new BizException(OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL);
        }
        for (TxnSensitiveCfg txnSensitiveCfg : txnSensitiveCfgList) {
            /* 从内部树中获取待脱敏字段的值 */
            String fieldValue;
            if (txnSensitiveCfg.getSensitiveField().contains("$n")) {
                int index = 1;
                String nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                while (!StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue(nextfield))) {
                    fieldValue = xmlTreeUtil.getXmlTreeStringValue(nextfield);
                    if (StringUtil.isEmptyOrNull(fieldValue)) {
                        rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行脱敏处理!", txnSensitiveCfg.getTxnNum(), nextfield);
                        continue;
                    }
                    /* 对待脱敏字段进行脱敏处理 */
                    String sensitiveValue = desensitiseCore(fieldValue, txnSensitiveCfg.getStartIndex(), txnSensitiveCfg.getEndIndex(), txnSensitiveCfg.getSensitiveChar());
                    rglog.debug("待脱敏的字段:<{}>,脱敏前:<{}>,脱敏后:<{}>", nextfield, fieldValue, sensitiveValue);
                    if (!StringUtil.isEmptyOrNull(cacheTime)) {
                        RedisUtil.onceSet(cacheName + sensitiveValue, fieldValue, Integer.parseInt(cacheTime));
                    } else {
                        RedisUtil.onceSet(cacheName + sensitiveValue, fieldValue, Integer.parseInt(SENSITIVE_INFO_CACHE_TIME));
                    }
                    sensitiveMap.put(fieldValue, sensitiveValue);
                    xmlTreeUtil.setXmlTreeStringValue(nextfield, sensitiveValue);
                    index++;
                    nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                }
            } else {
                fieldValue = xmlTreeUtil.getXmlTreeStringValue(txnSensitiveCfg.getSensitiveField());
                if (StringUtil.isEmptyOrNull(fieldValue)) {
                    rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行脱敏处理!", txnSensitiveCfg.getTxnNum(), txnSensitiveCfg.getSensitiveField());
                    continue;
                }
                /* 对待脱敏字段进行脱敏处理 */
                String sensitiveValue = desensitiseCore(fieldValue, txnSensitiveCfg.getStartIndex(), txnSensitiveCfg.getEndIndex(), txnSensitiveCfg.getSensitiveChar());
                rglog.debug("待脱敏的字段:<{}>,脱敏前:<{}>,脱敏后:<{}>", txnSensitiveCfg.getSensitiveField(), fieldValue, sensitiveValue);
                if (!StringUtil.isEmptyOrNull(cacheTime)) {
                    RedisUtil.onceSet(cacheName + sensitiveValue, fieldValue, Integer.parseInt(cacheTime));
                } else {
                    RedisUtil.onceSet(cacheName + sensitiveValue, fieldValue, Integer.parseInt(SENSITIVE_INFO_CACHE_TIME));
                }
                sensitiveMap.put(fieldValue, sensitiveValue);
                xmlTreeUtil.setXmlTreeStringValue(txnSensitiveCfg.getSensitiveField(), sensitiveValue);
            }

        }
        return sensitiveMap;
    }

    @Override
    public Map<String, String> desensitise(String field, String fieldValue, String fieldType, String cacheName, String cacheTime) throws Exception {
        Map<String, String> sensitiveMap = new HashMap<>();
        /* 根据字段类型对脱敏起始和截止位置赋值 */
        int startIndex;
        int endIndex;
        if (SensitiveTypeEnum.PHONE_NO.getType().equals(fieldType)) {
            startIndex = 3;
            endIndex = 4;
        } else if (SensitiveTypeEnum.BANK_CARD.getType().equals(fieldType)) {
            startIndex = 4;
            endIndex = 6;
        } else if (SensitiveTypeEnum.BANK_ACCT.getType().equals(fieldType)) {
            startIndex = 4;
            endIndex = 6;
        } else if (SensitiveTypeEnum.CERT_NO.getType().equals(fieldType)) {
            startIndex = 6;
            endIndex = 4;
        } else if (SensitiveTypeEnum.CUSTOMER_NAME.getType().equals(fieldType)) {
            startIndex = 0;
            endIndex = 1;
        } else {
            rglog.error("不支持的字段脱敏类型:{}，不进行脱敏!", fieldType);
            sensitiveMap.put(field, fieldValue);
            return sensitiveMap;
        }
        /* 对待脱敏字段进行脱敏处理 */
        String sensitiveValue = desensitiseCore(fieldValue, startIndex, endIndex, "*");
        rglog.debug("待脱敏的字段:<{}>,脱敏前:<{}>,脱敏后:<{}>", field, fieldValue, sensitiveValue);
        if (StringUtil.isEmptyOrNull(sensitiveValue) || StringUtil.isEmptyOrNull(cacheName)) {
            rglog.error("敏感信息:{}或者缓存名:{}为空!", sensitiveValue, cacheName);
            throw new BizException(OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL);
        }
        if (!StringUtil.isEmptyOrNull(cacheTime)) {
            RedisUtil.onceSet(cacheName + sensitiveValue, fieldValue, Integer.parseInt(cacheTime));
        } else {
            RedisUtil.onceSet(cacheName + sensitiveValue, fieldValue, Integer.parseInt(SENSITIVE_INFO_CACHE_TIME));
        }
        sensitiveMap.put(fieldValue, sensitiveValue);
        return sensitiveMap;
    }

    @Override
    public Map<String, String> recovery(String cacheName) throws Exception {
        BizHeader bizHeader = new BizHeader();
        ConvertUtil.convertOutput(bizHeader);
        if (StringUtil.isEmptyOrNull(bizHeader.getInstId()) || StringUtil.isEmptyOrNull(bizHeader.getSrcSysId()) ||
                StringUtil.isEmptyOrNull(bizHeader.getTxnNum()) || StringUtil.isEmptyOrNull(bizHeader.getBizType())) {
            rglog.error("无法获取交易信息，不进行敏感信息脱敏处理!");
            return null;
        }
        if (StringUtil.isEmptyOrNull(cacheName) && StringUtil.isEmptyOrNull(bizHeader.getSession())) {
            rglog.error("敏感信息缓存名或者会话ID同时为空，不进行敏感信息脱敏处理!");
            return null;
        }
        /* 敏感信息缓存名为空时，默认以session会话ID为缓存名 */
        cacheName = StringUtil.isEmptyOrNull(cacheName) ? bizHeader.getSession() : cacheName;
        /* 获取交易敏感信息配置信息 */
        TxnSensitiveCfgMapper txnSensitiveCfgMapper = new TxnSensitiveCfgMapperImpl();
        String txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + bizHeader.getBizType().trim() + "01";
        List<TxnSensitiveCfg> txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
        if (null == txnSensitiveCfgList) {
            txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), bizHeader.getBizType(), "01");
            if (null == txnSensitiveCfgList && !"*".equals(bizHeader.getBizType())) {
                rglog.info("查询当前交易通用的敏感信息恢复配置！");
                txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + "*01";
                txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
                if (null == txnSensitiveCfgList) {
                    txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), "*", "01");
                }
            }
        }
        return recovery(txnSensitiveCfgList, cacheName);
    }

    @Override
    public Map<String, String> recovery(List<TxnSensitiveCfg> txnSensitiveCfgList, String cacheName) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Map<String, String> sensitiveMap = new HashMap<>();
        if (null == txnSensitiveCfgList || txnSensitiveCfgList.isEmpty()) {
            rglog.debug("交易敏感配置信息为空，不进行脱敏恢复处理!");
            return null;
        }
        if (StringUtil.isEmptyOrNull(cacheName)) {
            rglog.error("缓存名:{}为空!", cacheName);
            throw new BizException(OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL);
        }
        for (TxnSensitiveCfg txnSensitiveCfg : txnSensitiveCfgList) {
            /* 从内部树中获取待脱敏字段的值 */
            String sensitiveValue;
            if (txnSensitiveCfg.getSensitiveField().contains("$n")) {
                int index = 1;
                String nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                while (!StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue(nextfield))) {
                    sensitiveValue = xmlTreeUtil.getXmlTreeStringValue(nextfield);
                    if (StringUtil.isEmptyOrNull(sensitiveValue)) {
                        rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行脱敏恢复处理!", txnSensitiveCfg.getTxnNum(), nextfield);
                        continue;
                    }
                    /* 对脱敏字段进行恢复脱敏处理 */
                    String fieldValue = RedisUtil.onceGet(cacheName + sensitiveValue);
                    sensitiveMap.put(sensitiveValue, fieldValue);
                    xmlTreeUtil.setXmlTreeStringValue(nextfield, fieldValue);
                    rglog.debug("待恢复脱敏的字段:<{}>,恢复脱敏前:<{}>,恢复脱敏后:<{}>", nextfield, sensitiveValue, fieldValue);
                    index++;
                    nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                }
            } else {
                sensitiveValue = xmlTreeUtil.getXmlTreeStringValue(txnSensitiveCfg.getSensitiveField());
                if (StringUtil.isEmptyOrNull(sensitiveValue)) {
                    rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行脱敏恢复处理!", txnSensitiveCfg.getTxnNum(), txnSensitiveCfg.getSensitiveField());
                    continue;
                }
                /* 对脱敏字段进行恢复脱敏处理 */
                String fieldValue = RedisUtil.onceGet(cacheName + sensitiveValue);
                sensitiveMap.put(sensitiveValue, fieldValue);
                xmlTreeUtil.setXmlTreeStringValue(txnSensitiveCfg.getSensitiveField(), fieldValue);
                rglog.debug("待恢复脱敏的字段:<{}>,恢复脱敏前:<{}>,恢复脱敏后:<{}>", txnSensitiveCfg.getSensitiveField(), sensitiveValue, fieldValue);
            }
        }
        return sensitiveMap;
    }

    @Override
    public Map<String, String> recovery(String field, String sensitiveValue, String cacheName) throws Exception {
        Map<String, String> sensitiveMap = new HashMap<>();
        if (StringUtil.isEmptyOrNull(sensitiveValue) || StringUtil.isEmptyOrNull(cacheName)) {
            rglog.error("敏感信息:{}或者缓存名:{}为空!", sensitiveValue, cacheName);
            throw new BizException(OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL);
        }
        /* 对脱敏字段进行恢复脱敏处理 */
        String fieldValue = RedisUtil.onceGet(cacheName + sensitiveValue);
        sensitiveMap.put(sensitiveValue, fieldValue);
        rglog.debug("待恢复脱敏的字段:<{}>,恢复脱敏前:<{}>,恢复脱敏后:<{}>", field, sensitiveValue, fieldValue);
        return sensitiveMap;
    }

    @Override
    public Map<String, String> encrypt(String encryptKey, String algorithmType) throws Exception {
        BizHeader bizHeader = new BizHeader();
        ConvertUtil.convertOutput(bizHeader);
        if (StringUtil.isEmptyOrNull(bizHeader.getInstId()) || StringUtil.isEmptyOrNull(bizHeader.getSrcSysId()) ||
                StringUtil.isEmptyOrNull(bizHeader.getTxnNum()) || StringUtil.isEmptyOrNull(bizHeader.getBizType())) {
            rglog.error("无法获取交易信息，不进行敏感信息加密处理!");
            return null;
        }
        /* 获取交易敏感信息配置信息 */
        TxnSensitiveCfgMapper txnSensitiveCfgMapper = new TxnSensitiveCfgMapperImpl();
        String txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + bizHeader.getBizType().trim() + "02";
        List<TxnSensitiveCfg> txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
        if (null == txnSensitiveCfgList) {
            txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), bizHeader.getBizType(), "02");
            if (null == txnSensitiveCfgList && !"*".equals(bizHeader.getBizType())) {
                rglog.info("查询当前交易通用的敏感信息加密配置！");
                txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + "*02";
                txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
                if (null == txnSensitiveCfgList) {
                    txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), "*", "02");
                }
            }
        }
        return encrypt(txnSensitiveCfgList, encryptKey, algorithmType);
    }

    @Override
    public Map<String, String> encrypt(List<TxnSensitiveCfg> txnSensitiveCfgList, String encryptKey, String algorithmType) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Map<String, String> sensitiveMap = new HashMap<>();
        if (null == txnSensitiveCfgList || txnSensitiveCfgList.isEmpty()) {
            rglog.debug("交易敏感配置信息为空，不进行加密处理!");
            return null;
        }
        if (StringUtil.isEmptyOrNull(encryptKey)) {
            rglog.error("加密密钥为空!");
            throw new BizException(OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL);
        }
        for (TxnSensitiveCfg txnSensitiveCfg : txnSensitiveCfgList) {
            /* 从内部树中获取待加密字段的值 */
            String fieldValue;
            if (txnSensitiveCfg.getSensitiveField().contains("$n")) {
                int index = 1;
                String nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                while (!StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue(nextfield))) {
                    fieldValue = xmlTreeUtil.getXmlTreeStringValue(nextfield);
                    if (StringUtil.isEmptyOrNull(fieldValue)) {
                        rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行加密处理!", txnSensitiveCfg.getTxnNum(), nextfield);
                        continue;
                    }
                    /* 对敏感字段进行加密 */
                    String fieldEncryptValue = AESUtil.pkcs7CbcEncryptData(Base64.decodeBase64(encryptKey), Base64.encodeBase64(fieldValue.getBytes(StandardCharsets.UTF_8)));
                    sensitiveMap.put(fieldValue, fieldEncryptValue);
                    xmlTreeUtil.setXmlTreeStringValue(nextfield, fieldEncryptValue);
                    rglog.debug("待加密的字段:<{}>,加密前:<{}>,加密后:<{}>", nextfield, fieldValue, fieldEncryptValue);
                    index++;
                    nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                }
            } else {
                fieldValue = xmlTreeUtil.getXmlTreeStringValue(txnSensitiveCfg.getSensitiveField());
                if (StringUtil.isEmptyOrNull(fieldValue)) {
                    rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行加密处理!", txnSensitiveCfg.getTxnNum(), txnSensitiveCfg.getSensitiveField());
                    continue;
                }
                /* 对敏感字段进行加密 */
                String fieldEncryptValue = AESUtil.pkcs7CbcEncryptData(Base64.decodeBase64(encryptKey), Base64.encodeBase64(fieldValue.getBytes(StandardCharsets.UTF_8)));
                sensitiveMap.put(fieldValue, fieldEncryptValue);
                xmlTreeUtil.setXmlTreeStringValue(txnSensitiveCfg.getSensitiveField(), fieldEncryptValue);
                rglog.debug("待加密的字段:<{}>,加密前:<{}>,加密后:<{}>", txnSensitiveCfg.getSensitiveField(), fieldValue, fieldEncryptValue);
            }
        }
        return sensitiveMap;
    }

    @Override
    public Map<String, String> decrypt(String decryptKey, String algorithmType) throws Exception {
        BizHeader bizHeader = new BizHeader();
        ConvertUtil.convertOutput(bizHeader);
        if (StringUtil.isEmptyOrNull(bizHeader.getInstId()) || StringUtil.isEmptyOrNull(bizHeader.getSrcSysId()) ||
                StringUtil.isEmptyOrNull(bizHeader.getTxnNum()) || StringUtil.isEmptyOrNull(bizHeader.getBizType())) {
            rglog.error("无法获取交易信息，不进行敏感信息加密处理!");
            return null;
        }
        /* 获取交易敏感信息配置信息 */
        TxnSensitiveCfgMapper txnSensitiveCfgMapper = new TxnSensitiveCfgMapperImpl();
        String txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + bizHeader.getBizType().trim() + "03";
        List<TxnSensitiveCfg> txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
        if (null == txnSensitiveCfgList) {
            txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), bizHeader.getBizType(), "03");
            if (null == txnSensitiveCfgList && !"*".equals(bizHeader.getBizType())) {
                rglog.info("查询当前交易通用的敏感信息解密配置！");
                txnSensitiveKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + bizHeader.getTxnNum().trim() + "*03";
                txnSensitiveCfgList = JSON.parseArray(RedisUtil.hashGet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, txnSensitiveKey), TxnSensitiveCfg.class);
                if (null == txnSensitiveCfgList) {
                    txnSensitiveCfgList = txnSensitiveCfgMapper.selectTxnSensitiveCfgByTxnNum(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), "*", "03");
                }
            }
        }
        return decrypt(txnSensitiveCfgList, decryptKey, algorithmType);
    }

    @Override
    public Map<String, String> decrypt(List<TxnSensitiveCfg> txnSensitiveCfgList, String decryptKey, String algorithmType) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Map<String, String> sensitiveMap = new HashMap<>();
        if (null == txnSensitiveCfgList || txnSensitiveCfgList.isEmpty()) {
            rglog.debug("交易敏感配置信息为空，不进行解密处理!");
            return null;
        }
        if (StringUtil.isEmptyOrNull(decryptKey)) {
            rglog.error("加密密钥为空!");
            throw new BizException(OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL);
        }
        for (TxnSensitiveCfg txnSensitiveCfg : txnSensitiveCfgList) {
            /* 从内部树中获取待解密字段的值 */
            String fieldEncryptValue;
            if (txnSensitiveCfg.getSensitiveField().contains("$n")) {
                int index = 1;
                String nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                while (!StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue(nextfield))) {
                    fieldEncryptValue = xmlTreeUtil.getXmlTreeStringValue(nextfield);
                    if (StringUtil.isEmptyOrNull(fieldEncryptValue)) {
                        rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行解密处理!", txnSensitiveCfg.getTxnNum(), nextfield);
                        continue;
                    }
                    /* 对加密字段进行解密 */
                    String decrypttValue = AESUtil.pkcs7CbcDecryptData(Base64.decodeBase64(decryptKey), Base64.decodeBase64(fieldEncryptValue.getBytes(StandardCharsets.UTF_8)));
                    sensitiveMap.put(fieldEncryptValue, decrypttValue);
                    xmlTreeUtil.setXmlTreeStringValue(nextfield, decrypttValue);
                    rglog.debug("待解密的字段:<{}>,解密前:<{}>,解密后:<{}>", nextfield, fieldEncryptValue, decrypttValue);
                    index++;
                    nextfield = txnSensitiveCfg.getSensitiveField().replace("$n", String.valueOf(index));
                }
            } else {
                fieldEncryptValue = xmlTreeUtil.getXmlTreeStringValue(txnSensitiveCfg.getSensitiveField());
                if (StringUtil.isEmptyOrNull(fieldEncryptValue)) {
                    rglog.info("交易码为<{}>的交易未上送字段<{}>，不进行解密处理!", txnSensitiveCfg.getTxnNum(), txnSensitiveCfg.getSensitiveField());
                    continue;
                }
                /* 对加密字段进行解密 */
                String decrypttValue = AESUtil.pkcs7CbcDecryptData(Base64.decodeBase64(decryptKey), Base64.decodeBase64(fieldEncryptValue.getBytes(StandardCharsets.UTF_8)));
                sensitiveMap.put(fieldEncryptValue, decrypttValue);
                xmlTreeUtil.setXmlTreeStringValue(txnSensitiveCfg.getSensitiveField(), decrypttValue);
                rglog.debug("待解密的字段:<{}>,解密前:<{}>,解密后:<{}>", txnSensitiveCfg.getSensitiveField(), fieldEncryptValue, decrypttValue);
            }
        }
        return sensitiveMap;
    }


    /**
     * 敏感字段信息脱敏处理
     *
     * @param fiedValue     敏感字段
     * @param startIndex    脱敏开始位置
     * @param endIndex      脱敏截止位置
     * @param sensitiveChar 脱敏替换字符
     * @return 脱敏后的字段值
     */
    private String desensitiseCore(String fiedValue, int startIndex, int endIndex, String sensitiveChar) {
        int desensitiseLength = fiedValue.length() > endIndex ? (fiedValue.length() - endIndex) : endIndex;
        rglog.debug("fieldValueLength:{},startIndex:{},endIndex:{},desensitiseLength:{}", fiedValue.length(), startIndex, endIndex, desensitiseLength);
        if (StringUtil.isEmptyOrNull(fiedValue) || startIndex > desensitiseLength) {
            return "";
        }
        if (startIndex == desensitiseLength) {
            return fiedValue.replaceFirst(fiedValue.substring(startIndex), sensitiveChar);
        }
        if (fiedValue.length() <= startIndex) {
            return fiedValue;
        }
        StringBuilder stringBuffer = new StringBuilder(fiedValue.substring(0, startIndex));
        for (int index = startIndex; index < desensitiseLength; index++) {
            stringBuffer.append(sensitiveChar);
        }
        if (fiedValue.length() >= endIndex) {
            stringBuffer.append(fiedValue.substring(desensitiseLength));
        }
        return stringBuffer.toString() + "|" + RandomUtil.getUUID();
    }
}
